Skip to content

Conversation

@YanVictorSN
Copy link
Contributor

@YanVictorSN YanVictorSN commented Jul 28, 2025

Description

A component that show claimers a set of tasks they can complete.

About #228

  • There is always a main task highlighted
  • Alternative tasks should show, but in a less prominent way
  • Should fit existing styling/design.
  • UX/UI should be intuitive.
  • should be able to dismiss tasks (not show) for the next 4 days.
  • tasks can have rewards associated (only UI, no payments are triggered)
  • tasks will have durations for how long they will show
Captura de tela 2025-08-06 124552

Description by Korbit AI

What change is being made?

Add a new ClaimerTasksCard component to manage and display user tasks with capabilities to mark tasks as complete or dismissed and integrate this with existing stories.

Why are these changes being made?

These changes address the need to manage user engagement by allowing users to interact with tasks, enhancing the user experience by providing clear task rewards and statuses. This approach utilizes React and native-base for robust UI management, with efficient state handling using hooks. However, reliance on AsyncStorage may warrant future revisits for optimized performance.

Is this description stale? Ask me to generate a new description by commenting /korbit-generate-pr-description

Copy link

@korbit-ai korbit-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by Korbit AI

Korbit automatically attempts to detect when you fix issues in new commits.
Category Issue Status
Functionality Incomplete Task Action Handling ▹ view ✅ Fix detected
Performance Sequential Async Storage Reads ▹ view ✅ Fix detected
Functionality Incomplete Task Completion Implementation ▹ view ✅ Fix detected
Performance Inefficient Date Operations in Loop ▹ view ✅ Fix detected
Design Poor Story Implementation Pattern ▹ view ✅ Fix detected
Functionality Missing Mock Data Implementation ▹ view ✅ Fix detected
Design Embedded Sample Data ▹ view ✅ Fix detected
Files scanned
File Path Reviewed
packages/good-design/src/apps/usertasks/ManagerTaskCards.stories.tsx
packages/good-design/src/apps/usertasks/managerTaskCard.tsx

Explore our documentation to understand the languages and file types we support and the files we ignore.

Check out our docs on how you can make Korbit work best for you and your team.

Loving Korbit!? Share us on LinkedIn Reddit and X

actionUrl?: string;
}

const SAMPLE_TASKS: ClaimerTask[] = [

This comment was marked as resolved.

}

export const ClaimerTasksCard: React.FC<ClaimerTasksCardProps> = ({ onTaskDismiss, fontStyles }) => {
const { mainTask, secondaryTasks, loading, hasActiveTasks, dismissTask } = useClaimerTasks();

This comment was marked as resolved.

Comment on lines 176 to 184
const openTask = async (task: ClaimerTask) => {
if (task.actionUrl) {
try {
await Linking.openURL(task.actionUrl);
} catch (error) {
console.warn("Failed to open task URL:", error);
}
}
};

This comment was marked as resolved.

Comment on lines 67 to 68
const dismissed = await AsyncStorage.getItem("dismissed_claimer_tasks");
const completed = await AsyncStorage.getItem("completed_claimer_tasks");

This comment was marked as resolved.

Comment on lines 91 to 106
const availableTasks = useMemo(() => {
const now = new Date();
const fourDays = 4 * 24 * 60 * 60 * 1000;

return SAMPLE_TASKS.filter(task => {
const start = new Date(task.duration.startDate);
const end = new Date(task.duration.endDate);
if (now < start || now > end) return false;
if (completedTasks.includes(task.id)) return false;

const dismissed = dismissedTasks[task.id];
if (dismissed && now.getTime() - dismissed < fourDays) return false;

return true;
});
}, [dismissedTasks, completedTasks]);

This comment was marked as resolved.

export const WithMockData = () => (
<NativeBaseProvider>
<ClaimerTasksCompact
//tasks={tasksData}

This comment was marked as resolved.

Comment on lines 10 to 18
export const WithMockData = () => (
<NativeBaseProvider>
<ClaimerTasksCompact
//tasks={tasksData}
onTaskComplete={taskId => console.log("Task completed:", taskId)}
onTaskDismiss={taskId => console.log("Task dismissed:", taskId)}
/>
</NativeBaseProvider>
);

This comment was marked as resolved.

@YanVictorSN
Copy link
Contributor Author

Hi @vortex-hue! I opened this draft since our tickets are related, thought it might help us both. If you’d like to work on the same branch or need any help, just let me know!

@vortex-hue
Copy link
Contributor

Hi @vortex-hue! I opened this draft since our tickets are related, thought it might help us both. If you’d like to work on the same branch or need any help, just let me know!

Hi Victor, Thanks for the draft, am open to working together on this, are you available for a meet tomorrow?

@YanVictorSN
Copy link
Contributor Author

@vortex-hue Sure. How can I reach out to you?

@vortex-hue
Copy link
Contributor

@vortex-hue Sure. How can I reach out to you?

+2348115333313 WhatsApp or @devops_pete on telegram

@YanVictorSN YanVictorSN marked this pull request as ready for review August 1, 2025 13:06
@korbit-ai
Copy link

korbit-ai bot commented Aug 1, 2025

You've used up your 5 PR reviews for this month under the Korbit Starter Plan. You'll get 5 more reviews on August 19th, 2025 or you can upgrade to Pro for unlimited PR reviews and enhanced features in your Korbit Console.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @YanVictorSN - I've reviewed your changes - here's some feedback:

  • The tasks prop on ClaimerTasksCard is never used—refactor the hook/component to accept injected task lists instead of always relying on SAMPLE_TASKS.
  • Consider extracting the date‐range and dismissal filtering logic into a pure utility function for easier testing and reuse outside the hook.
  • Repeated AsyncStorage writes on each dismiss or complete action could impact performance—consider debouncing or batching persistence updates.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `tasks` prop on ClaimerTasksCard is never used—refactor the hook/component to accept injected task lists instead of always relying on SAMPLE_TASKS.
- Consider extracting the date‐range and dismissal filtering logic into a pure utility function for easier testing and reuse outside the hook.
- Repeated AsyncStorage writes on each dismiss or complete action could impact performance—consider debouncing or batching persistence updates.

## Individual Comments

### Comment 1
<location> `packages/good-design/src/apps/usertasks/managerTaskCard.tsx:26` </location>
<code_context>
+  actionUrl?: string;
+}
+
+export const useClaimerTasks = () => {
+  const [dismissedTasks, setDismissedTasks] = useState<{ [key: string]: number }>({});
+  const [completedTasks, setCompletedTasks] = useState<string[]>([]);
</code_context>

<issue_to_address>
The useClaimerTasks hook does not use the 'tasks' prop from ClaimerTasksCard.

Since useClaimerTasks always uses SAMPLE_TASKS, any 'tasks' prop passed to ClaimerTasksCard is ignored. Refactor useClaimerTasks to accept a tasks argument or clarify the intended usage to avoid confusion or bugs.
</issue_to_address>

### Comment 2
<location> `packages/good-design/src/apps/usertasks/managerTaskCard.tsx:76` </location>
<code_context>
+    }
+  };
+
+  const dismissAllTasks = async (taskIds: string[], onTaskDismiss?: (taskId: string) => void) => {
+    setDismissing(true);
+    const now = Date.now();
</code_context>

<issue_to_address>
Potential race condition when dismissing all tasks due to state update timing.

Since setDismissedTasks is asynchronous, the state may not be updated before persisting to AsyncStorage. Use a functional update or ensure the latest state is saved.
</issue_to_address>

### Comment 3
<location> `packages/good-design/src/apps/usertasks/mockData.ts:10` </location>
<code_context>
+    category: "engagement",
+    priority: "main",
+    reward: { type: "tokens", amount: 10, description: "Vote on" },
+    duration: { startDate: "2025-07-23", endDate: "2025-08-23" },
+    actionUrl: "https://www.gooddollar.org/"
+  },
</code_context>

<issue_to_address>
Sample task dates are set in the future, which may affect development and testing.

Using fixed future dates may hinder testing of time-dependent features. Consider switching to relative dates or document this choice for clarity.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

actionUrl?: string;
}

export const useClaimerTasks = () => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): The useClaimerTasks hook does not use the 'tasks' prop from ClaimerTasksCard.

Since useClaimerTasks always uses SAMPLE_TASKS, any 'tasks' prop passed to ClaimerTasksCard is ignored. Refactor useClaimerTasks to accept a tasks argument or clarify the intended usage to avoid confusion or bugs.

}
};

const dismissAllTasks = async (taskIds: string[], onTaskDismiss?: (taskId: string) => void) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Potential race condition when dismissing all tasks due to state update timing.

Since setDismissedTasks is asynchronous, the state may not be updated before persisting to AsyncStorage. Use a functional update or ensure the latest state is saved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: manage user tasks

3 participants